﻿using System;
using System.Data.SqlServerCe;
using System.IO;
using System.Reflection;
using System.Text;

namespace DB
{
    /// <summary>
    /// DBアクセッサクラス
    /// </summary>
    public class DBAccessor : IDisposable
    {
        #region 定数
        /// <summary>DBファイル名</summary>
        private const string DB_FILE_NAME = @"sample_db.sdf";

        /// <summary>接続文字列</summary>
        private const string CONNECTION_STR = @"Data Source=sample_db.sdf; LCID=1033; Password = sampledbpw; Encrypt = TRUE;";

        /// <summary>テーブル作成SQLファイル</summary>
        private const string FILE_CREATE_TABLE = @"DB.SQL.CreateTable.sql";

        /// <summary>テーブル作成SQLファイル</summary>
        private const string FILE_CREATE_TABLE2 = @"DB.SQL.CreateTable2.sql";


        #endregion

        #region プロパティ
        /// <summary>
        /// 接続情報
        /// </summary>
        public SqlCeConnection Con { get; set; }

        /// <summary>
        /// トランザクション
        /// </summary>
        public SqlCeTransaction Transaction { get; set; }

        #endregion

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public DBAccessor() 
        {
            // 初期化処理
            Init();

            // 接続情報の作成
            Con = new SqlCeConnection(CONNECTION_STR);
            Con.Open();
        }

        /// <summary>
        /// Dispose
        /// </summary>
        public void Dispose()
        {
            Close();
        }

        #region public
        /// <summary>
        /// DBオープン
        /// </summary>
        public static DBAccessor Opne()
        {
            return new DBAccessor();
        }

        /// <summary>
        /// トランザクションを開始状態でDBオープン
        /// </summary>
        public static DBAccessor BeginTransactionOpne()
        {
            var db = new DBAccessor();
            db.Transaction = db.Con.BeginTransaction();
            return db;
        }

        /// <summary>
        /// DBクローズ
        /// </summary>
        public void Close() 
        {
            Con.Close();
        }

        /// <summary>
        /// コミット
        /// </summary>
        public void Commit() 
        {
            if (Transaction == null) 
            {
                return;
            }

            Transaction.Commit();
        }

        /// <summary>
        /// ロールバック
        /// </summary>
        public void Rollback()
        {
            if (Transaction == null)
            {
                return;
            }

            Transaction.Rollback();
        }

        #endregion

        #region private
        /// <summary>
        /// 初期化処理
        /// </summary>
        private void Init()
        {
            // DBファイルが存在しない場合
            if (!File.Exists(DB_FILE_NAME))
            {
                // DBファイルを作成する
                CreateDBFile();
            }
        }

        /// <summary>
        /// DBファイルを作成する
        /// </summary>
        private static void CreateDBFile() 
        {
            // DBを作成する
            var engine = new SqlCeEngine(CONNECTION_STR);
            engine.CreateDatabase();

            // コネクションを作成して開く
            using (var db = Opne())
            {
                // テーブルを作成する
                var command = new SqlCeCommand(ReadSQLFile(FILE_CREATE_TABLE, Encoding.UTF8), db.Con);
                command.ExecuteNonQuery();
            }
        }

        /// <summary>
        /// SQLファイル読み込み
        /// </summary>
        /// <param name="sqlFile">SQLファイル</param>
        /// <param name="encoding">エンコーディング</param>
        /// <returns>SQL文字列</returns>
        internal static string ReadSQLFile(string sqlFile, Encoding encoding) 
        {
            var sql = String.Empty;

            if (String.IsNullOrEmpty(sqlFile)) 
            {
                return sql;
            }

            Assembly assembly = Assembly.GetExecutingAssembly();

            // SQLファイルを読み込む
            using (var sr = new StreamReader(assembly.GetManifestResourceStream(sqlFile), encoding)) 
            {   
                sql = sr.ReadToEnd();
            }

            return sql;
        }

        #endregion

    }
}
